package com.bean.builder;

/**
 * 建造者模式
 * 指将一个复杂对象的构造与它的表示分离，使同样的构建过程可以创建不同的表示，这样的设计模式被称为建造者模式。
 * 它是将一个复杂的对象分解为多个简单的对象，然后一步一步构建而成。它将变与不变相分离，即产品的组成部分是不变的，但每一部分是可以灵活选择的。
 * @author 顾志杰
 * @date 2021/8/9-9:25
 */
public class Builder {

    /**
     * 虚线是实现 实线是继承
     *
     * 该模式的主要优点如下：
     * 1.封装性好，构建和表示分离。
     * 2.扩展性好，各个具体的建造者相互独立，有利于系统的解耦。
     * 3.客户端不必知道产品内部组成的细节，建造者可以对创建过程逐步细化，而不对其它模块产生任何影响，便于控制细节风险。
     *
     * 其缺点如下：
     * 1.产品的组成部分必须相同，这限制了其使用范围。
     * 2.如果产品的内部变化复杂，如果产品内部发生变化，则建造者也要同步修改，后期维护成本较大。
     */

    /**
     * 模式的结构
     * 1.建造者（Builder）模式的主要角色如下。
     * 2.产品角色（Product）：它是包含多个组成部件的复杂对象，由具体建造者来创建其各个零部件。
     * 3.抽象建造者（Builder）：它是一个包含创建产品各个子部件的抽象方法的接口，通常还包含一个返回复杂产品的方法 getResult()。
     * 4.具体建造者(Concrete Builder）：实现 Builder 接口，完成复杂产品的各个部件的具体创建方法。
     * 5.指挥者（Director）：它调用建造者对象中的部件构造与装配方法完成复杂对象的创建，在指挥者中不涉及具体产品的信息。
     */

    public static void main(String[] args) {
        BuilderBean builder = new ConcreteBuilder();
        Director director = new Director(builder);
        Product product = director.construct();
        product.show();
    }
}

/**
 * 产品角色：包含多个组成部件的复杂对象
 */
class Product {
    private String partA;
    private String partB;
    private String partC;
    public void setPartA(String partA) {
        this.partA = partA;
    }
    public void setPartB(String partB) {
        this.partB = partB;
    }
    public void setPartC(String partC) {
        this.partC = partC;
    }
    public void show() {
        System.out.println("partA = "+ partA);
        System.out.println("partB = "+ partB);
        System.out.println("partC = "+ partC);
        //显示产品的特性
    }
}

/**
 *  抽象建造者：包含创建产品各个子部件的抽象方法。
 */
abstract class BuilderBean {
    //创建产品对象
    protected Product product = new Product();
    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();
    //返回产品对象
    public Product getResult() {
        return product;
    }
}

/**
 * 具体建造者：实现了抽象建造者接口。
 */
class ConcreteBuilder extends BuilderBean {
    public void buildPartA() {
        product.setPartA("建造 PartA");
    }
    public void buildPartB() {
        product.setPartB("建造 PartB");
    }
    public void buildPartC() {
        product.setPartC("建造 PartC");
    }
}

/**
 * 指挥者：调用建造者中的方法完成复杂对象的创建。
 */
class Director {
    private BuilderBean builder;
    public Director(BuilderBean builder) {
        this.builder = builder;
    }
    //产品构建与组装方法
    public Product construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}
